package com.example.musictutor.activities;

import java.util.ArrayList;
import java.util.List;

import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewGroup;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;

import com.example.musictutor.R;
import com.example.musictutor.domain.Note;
import com.example.musictutor.domain.ProgressHistory;
import com.example.musictutor.domain.Song;
import com.example.musictutor.domain.SongNote;
import com.example.musictutor.repository.facade.impl.NoteDAOFacade;
import com.example.musictutor.repository.facade.impl.ProgressHistoryDAOFacade;
import com.example.musictutor.repository.facade.impl.SongDAOFacade;
import com.example.musictutor.services.KeyBoard;
import com.example.musictutor.services.MatchSongs;
import com.example.musictutor.services.PlaySong;
import com.example.musictutor.services.RecordSong;
import com.example.musictutor.views.KeyButton;

// TODO
// Apply same observer pattern to playrunnable and implement playsong as main

public class PlaySongActivity extends FragmentActivity {

    public static final int STATE_CORRECT = 1;
    public static final int STATE_INCORRECT = 2;

    public static final int PLAY_BUTTON = 0;
    public static final int PAUSE_BUTTON = 1;
    public static final int RESTART_BUTTON = 2;

    private static Song newSong = null;
    //private static Song testSong = null;

    private static PlaySong mPlaySong;

    private static int mCorrectState = 0;

    private ProgressHistory progressHistoryPerLevel;
    private ProgressHistoryDAOFacade progressHistoryDAOFacade;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_play_song);

        RecordSong recordsong = RecordSong.getInstance();
        recordsong.setContext(this);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
            mCorrectState = 0;
        }

        PlaceholderFragment fragment = (PlaceholderFragment) getSupportFragmentManager()
                .findFragmentById(R.id.container);

        if(getIntent().hasExtra("songId")) {
            long songId = getIntent().getLongExtra("songId", 0);

            SongDAOFacade dao = new SongDAOFacade(this);
            Song song = dao.findEntityById(songId);

            mPlaySong = new PlaySong(song, this);

            progressHistoryDAOFacade = new ProgressHistoryDAOFacade(this);
            //get the progress for this song if no progress create one and update
           if(progressHistoryDAOFacade.getProgressHistoryForSongLevel((int)songId)!=null){
                progressHistoryPerLevel = progressHistoryDAOFacade.getProgressHistoryForSongLevel((int)songId);
           }else{
                Toast.makeText(this,"There was an error retrieving progress history for the user",2).show();
           }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    public void functionButtonPressed(int button) {
        ImageButton playSongButton = (ImageButton) findViewById(R.id.playSongButton);
        ImageButton pauseSongButton = (ImageButton) findViewById(R.id.pauseSongButton);
        ImageButton restartSongButton = (ImageButton) findViewById(R.id.restartSongButton);

        switch (button) {
            case PLAY_BUTTON:
                playSongButton.setImageResource(R.drawable.play_selected_image);
                pauseSongButton.setImageResource(R.drawable.pause_image);
                restartSongButton.setImageResource(R.drawable.restart_image);
                break;

            case PAUSE_BUTTON:
                if (mPlaySong.getState() == PlaySong.ACTIVE) {
                    playSongButton.setImageResource(R.drawable.play_image);
                    pauseSongButton.setImageResource(R.drawable.pause_selected_image);
                    restartSongButton.setImageResource(R.drawable.restart_image);
                }
                break;

            case RESTART_BUTTON:
                if (mPlaySong.getState() == PlaySong.ACTIVE) {
                    playSongButton.setImageResource(R.drawable.play_image);
                    pauseSongButton.setImageResource(R.drawable.pause_image);
                    restartSongButton.setImageResource(R.drawable.restart_selected_image);
                }
                break;
        }
    }

    public void setRecordOn(boolean setOn) {
        ImageButton button = (ImageButton) findViewById(R.id.recordButton);
        TextView text = (TextView) findViewById(R.id.recordHintLabel);
        if (setOn) {
            button.setImageResource(R.drawable.record_on_image);
            text.setText(getResources().getString(R.string.recordStopHint));

            //means user attempted to playback song so increment count by one
            int currentCount = progressHistoryPerLevel.getAmountOfAttempts();
            progressHistoryPerLevel.setAmountOfAttempts(currentCount+1);
            progressHistoryDAOFacade.updateEntity(progressHistoryPerLevel);

        } else {
            button.setImageResource(R.drawable.record_off_image);
            text.setText(getResources().getString(R.string.recordStartHint));
        }
    }

    public void setBackgroundDimmed(boolean enabled, int resourceId) {
        RelativeLayout layout = (RelativeLayout) findViewById(R.id.suspendStatusLayout);
        ImageButton button = (ImageButton) findViewById(R.id.suspendStatusImage);

        if(enabled) {
            button.setBackgroundResource(resourceId);

            Animation animation = AnimationUtils.loadAnimation(this,
                    R.anim.dim_background);
            layout.startAnimation(animation);

            layout.setVisibility(View.VISIBLE);
            button.setVisibility(View.VISIBLE);
        }
        else {
            layout.setVisibility(View.INVISIBLE);
            button.setVisibility(View.INVISIBLE);
        }
    }

    public void isListening(boolean isListening) {
        ImageView imageView = (ImageView) findViewById(R.id.suspendStatusImage);

        if(isListening)
            imageView.setBackgroundResource(R.drawable.listening_active_image);
        else
            imageView.setBackgroundResource(R.drawable.listening_image);
    }

    public void songFinished() {
        RelativeLayout layout = (RelativeLayout) findViewById(R.id.suspendStatusLayout);
        ImageButton button = (ImageButton) findViewById(R.id.suspendStatusImage);

        layout.setVisibility(View.INVISIBLE);
        button.setVisibility(View.INVISIBLE);

        KeyBoard.getInstance().setEnabled(true);

        ImageView timerView = (ImageView) findViewById(R.id.timerImage);
        timerView.setBackgroundResource(R.drawable.timer_animation);
        AnimationDrawable animation = (AnimationDrawable) timerView.getBackground();
        animation.start();

        Thread thread = new Thread(timerRunnable);
        thread.start();
    }

    @Override
    public void onBackPressed() {
        RecordSong.getInstance().setState(RecordSong.STATE_NOT_RECORDING);
        super.onBackPressed();
    }

    private int mTime = 0;
    private boolean mTimerIsRunning = false;
    private Runnable timerRunnable = new Runnable() {

        int count;

        @Override
        public void run() {
            count = 0;
            mTimerIsRunning = true;

            while(mTimerIsRunning) {
                if(count < 2) {
                    count++;
                }
                else {
                    mTime++;
                }

                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            mTime = 0;
        }

    };

    public void startRemoveAnimation() {
        LinearLayout layout = (LinearLayout) findViewById(R.id.songFunctionsLayout);
        Button doneButton = (Button) this.findViewById(R.id.doneSongButton);

        for (int i = 0; i < layout.getChildCount(); i++) {
            View child = layout.getChildAt(i);
            child.setEnabled(false);
        }
        doneButton.setEnabled(false);

        Animation animation = AnimationUtils.loadAnimation(this, R.anim.remove_play_functions);
        animation.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                hidePlayFunctions();
            }
        });

        layout.startAnimation(animation);
        doneButton.startAnimation(animation);

        ImageButton recordButton = (ImageButton) findViewById(R.id.recordButton);
        recordButton.setEnabled(true);
        Animation fadeAnimation = AnimationUtils.loadAnimation(
                this, R.anim.fade_in_button);
        fadeAnimation.setAnimationListener(new AnimationListener() {

            @Override
            public void onAnimationStart(Animation animation) {

            }

            @Override
            public void onAnimationRepeat(Animation animation) {

            }

            @Override
            public void onAnimationEnd(Animation animation) {
                showRecordHint();
            }
        });
        recordButton.startAnimation(fadeAnimation);
        recordButton.setVisibility(View.VISIBLE);

        ImageView timerImage = (ImageView) findViewById(R.id.timerImage);
        timerImage.setVisibility(View.INVISIBLE);

        TextView timerText = (TextView) findViewById(R.id.timeText);
        timerText.setText(getTimertext());
        timerText.setVisibility(View.VISIBLE);
    }

    private String getTimertext() {
        int time = mTime;

        String minutesLabel = "00";
        String secondsLabel = "00";

        int minutes = 0;

        if(time > 60) {
            double minutesDecimal = time / 60;
            minutes = (int) minutesDecimal;

            if(minutes < 10)
                minutesLabel = "0" + minutes;
            else
                minutesLabel = "" + minutes;
        }

        int seconds = time % 60;

        if(seconds < 10)
            secondsLabel = "0" + seconds;
        else
            secondsLabel = "" + seconds;

        return minutesLabel + ":" + secondsLabel;
    }

    public void showRecordHint() {
        TextView hint = (TextView) findViewById(R.id.recordHintLabel);
        hint.setVisibility(View.VISIBLE);
    }

    public void hidePlayFunctions() {
        LinearLayout layout = (LinearLayout) findViewById(R.id.songFunctionsLayout);
        Button doneButton = (Button) findViewById(R.id.doneSongButton);
        layout.setVisibility(View.INVISIBLE);
        doneButton.setVisibility(View.INVISIBLE);
    }

    public void prepareForRecord() {
        startRemoveAnimation();
        KeyBoard.getInstance().setEnabled(false);
        mTimerIsRunning = false;

        ImageView timerView = (ImageView) findViewById(R.id.timerImage);
        timerView.setBackgroundResource(R.drawable.timer_animation);
        AnimationDrawable animation = (AnimationDrawable) timerView.getBackground();
        animation.stop();
        // TODO: set state
    }

    public void startRecording() {
        RecordSong recordSong = RecordSong.getInstance();

        if (recordSong.getState() == RecordSong.STATE_NOT_RECORDING) {
            setRecordOn(true);
            recordSong.startRecording(120);
            //setBackgroundDimmed(true);
            // TODO: set state
        } else if (recordSong.getState() == RecordSong.STATE_RECORDING) {
            setRecordOn(false);
            Song newSong = recordSong.stopRecording();

            //means user attempted to playback song so increment count by one
            int currentCount = progressHistoryPerLevel.getAmountOfAttempts();
            int cuPassed = progressHistoryPerLevel.getAmountPassed();
            int cuFailed = progressHistoryPerLevel.getAmountFailed();

            if (newSong != null) {
                MatchSongs matchSongs = new MatchSongs();
                int status = matchSongs.compareSongs(mPlaySong.getSong(), newSong);

                if(status == 0) {
                    setBackgroundDimmed(true, R.drawable.correct_image);
                    mCorrectState = STATE_CORRECT;

                    SongDAOFacade dao = new SongDAOFacade(this);

                    Song updatedSong = mPlaySong.getSong();
                    updatedSong.setHighscore(mTime);
                    updatedSong.setUnlocked(true);
                    dao.updateEntity(updatedSong);
                    progressHistoryPerLevel.setAmountPassed(cuPassed+1);
                }
                else {
                    setBackgroundDimmed(true, R.drawable.incorrect_image);
                    mCorrectState = STATE_INCORRECT;
                    progressHistoryPerLevel.setAmountFailed(cuFailed+1);
                }

                progressHistoryDAOFacade.updateEntity(progressHistoryPerLevel);
            }

        }
        // TODO: set state
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.fragment_play_song,
                    container, false);

            KeyBoard keyboard = KeyBoard.getInstance();

            LinearLayout keysLayout = (LinearLayout) rootView
                    .findViewById(R.id.keysLayout);
            KeyButton key = null;
            LayoutParams params = null;
            Note note = null;

            NoteDAOFacade noteDao = new NoteDAOFacade(getActivity());
            List<Note> noteList = noteDao.getEntities();

            for (Note n : noteList) {
                key = new KeyButton(rootView.getContext());
                params = new LayoutParams(0, ViewGroup.LayoutParams.MATCH_PARENT);
                params.weight = 1;

                key.setLayoutParams(params);
                key.setPadding(10, 10, 10, 10);
                key.setBackgroundResource(R.drawable.white_key_selector);
                key.setText(n.getName());

                key.setNote(n);

                keysLayout.addView(key);
                keyboard.addKey(key);
            }

            ImageButton recordButton = (ImageButton) rootView
                    .findViewById(R.id.recordButton);
            recordButton.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        PlaySongActivity activity = (PlaySongActivity) getActivity();
                        activity.startRecording();
                    }

                    return false;
                }
            });

            Button playRecordingButton = (Button) rootView
                    .findViewById(R.id.playButton);
            playRecordingButton.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        Log.d("Song", "Entered play song...");
                        if (newSong != null) {
                            PlaySong playRecording = new PlaySong(newSong, v
                                    .getContext());
                            playRecording.playPressed();
                        }
                    }

                    return false;
                }
            });

			/*Button matchButton = (Button) rootView
					.findViewById(R.id.matchButton);
			matchButton.setOnTouchListener(new OnTouchListener() {

				@Override
				public boolean onTouch(View v, MotionEvent event) {

					if (event.getAction() == MotionEvent.ACTION_DOWN) {
						Log.d("Song", "Entered match song...");
						if (newSong != null) {
							MatchSongs matchSongs = new MatchSongs();
							int status = matchSongs.compareSongs(testSong,
									newSong);

							Log.d("Match Songs", "status - " + status);
							String statusText = "No status!";

							switch (status) {
							case 0:
								statusText = "Successful!";
								break;
							case 1:
								statusText = "Sorry, amount of notes was different.";
								break;
							case 2:
								statusText = "Sorry, the notes played was wrong.";
								break;
							case 3:
								statusText = "Sorry, the some of the note lengths was incorrect.";
								break;
							}

							Toast.makeText(v.getContext(), statusText, 3)
									.show();
						}

					}

					return false;
				}
			});*/

            ImageButton listenButton = (ImageButton) rootView
                    .findViewById(R.id.suspendStatusImage);

            listenButton.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        Log.d("Song", "Entered play song...");

                        if(mCorrectState == STATE_CORRECT) {
                            // Get list of all songs
                            SongDAOFacade dao = new SongDAOFacade(getActivity());
                            List<Song> songList = dao.getEntities();

                            long songId = -1;

                            // For the sake of not enought time, the first level found still locked should be the last played level
                            for(Song s :  songList) {
                                if(!s.isUnlocked()) {
                                    songId = s.getId();
                                    break;
                                }
                            }

                            // When all songs have been unlocked, for now just set id to any song
                            if(songId == -1)
                                songId = songList.get(1).getId();

                            Intent intent = new Intent(getActivity(), PlaySongActivity.class);
                            intent.putExtra("songId", songId);
                            startActivity(intent);
                        }
                        else if(mCorrectState == STATE_INCORRECT) {
                            Intent intent = new Intent(getActivity(), PlaySongActivity.class);
                            intent.putExtra("songId", mPlaySong.getSong().getId());
                            startActivity(intent);
                        }
                        else {
                            PlaySongActivity activity = (PlaySongActivity) getActivity();
                            activity.isListening(true);
                            mPlaySong.playPressed();
                        }
                    }

                    return false;
                }
            });

            InitializePlayerButton(rootView);

            PlaySongActivity activity = (PlaySongActivity) getActivity();

            return rootView;
        }

        public void InitializePlayerButton(View view) {

            Button doneButton = (Button) view.findViewById(R.id.doneSongButton);

            doneButton.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        PlaySongActivity activity = (PlaySongActivity) getActivity();
                        activity.prepareForRecord();
                    }

                    return false;
                }
            });

            ImageButton playSongButton = (ImageButton) view
                    .findViewById(R.id.playSongButton);

            playSongButton.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        Log.d("Song", "Entered play song...");
                        PlaySongActivity activity = (PlaySongActivity) getActivity();
                        activity.functionButtonPressed(PLAY_BUTTON);
                        mPlaySong.playPressed();
                    }

                    return false;
                }
            });

            ImageButton pauseSongButton = (ImageButton) view
                    .findViewById(R.id.pauseSongButton);
            pauseSongButton.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        Log.d("Song", "Entered play song...");
                        PlaySongActivity activity = (PlaySongActivity) getActivity();
                        activity.functionButtonPressed(PAUSE_BUTTON);
                        mPlaySong.pausePressed();
                    }

                    return false;
                }
            });

            ImageButton restartSongButton = (ImageButton) view
                    .findViewById(R.id.restartSongButton);
            restartSongButton.setOnTouchListener(new OnTouchListener() {

                @Override
                public boolean onTouch(View v, MotionEvent event) {
                    if (event.getAction() == MotionEvent.ACTION_DOWN) {
                        Log.d("Song", "Entered play song...");
                        PlaySongActivity activity = (PlaySongActivity) getActivity();
                        activity.functionButtonPressed(RESTART_BUTTON);
                        mPlaySong.restartPressed();
                    }

                    return false;
                }
            });
        }
    }

}
